package com.hycat.mail.common.utils;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * @author : lzhycat
 * @date : 2022-08-02 14:20
 */
public class CSVUtil {

    /**
     * @param headLabel 头部标签
     * @param dataList  数据列表
     * @param filePath  文件路径
     * @param addFlag   是否追加
     */
    public static void writeToCsv(String headLabel, List<String> dataList, String filePath, boolean addFlag) {
        BufferedWriter buffWriter = null;
        try {
            //根据指定路径构建文件对象
            File csvFile = new File(filePath);
            //文件输出流对象，第二个参数时boolean类型,为true表示文件追加（在已有的文件中追加内容）
            FileWriter writer = new FileWriter(csvFile, addFlag);
            //构建缓存字符输出流（不推荐使用OutputStreamWriter）
            buffWriter = new BufferedWriter(writer, 1024);
            //头部不为空则写入头部，并且换行
            if (org.apache.commons.lang3.StringUtils.isNotBlank(headLabel)) {
                buffWriter.write(headLabel);
                buffWriter.newLine();
            }
            //遍历list
            for (String rowStr : dataList) {
                //如果数据不为空，则写入文件内容,并且换行
                if (org.apache.commons.lang3.StringUtils.isNotBlank(rowStr)) {
                    buffWriter.write(rowStr);
                    buffWriter.newLine();//文件写完最后一个换行不用处理
                }
            }
            //刷新流，也就是把缓存中剩余的内容输出到文件
            buffWriter.flush();
        } catch (Exception e) {
            System.out.println("写入csv出现异常");
            e.printStackTrace();
        } finally {
            try {
                //关闭流
                if (buffWriter != null) {
                    buffWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 根据File文件读取csv文件的内容
     * @return
     */
    public static List<String> readFile(File csvFile) {
        ArrayList<String> dataList = new ArrayList<>();
        BufferedReader buffReader = null;
        try {
            //判断文件是否存在
            if (!csvFile.exists()) {
                System.out.println("文件不存在");
                return dataList;
            }
            //构建字符输入流
            FileReader fileReader = new FileReader(csvFile);
            //构建缓存字符输入流
            buffReader = new BufferedReader(fileReader);
            String line = "";
            //根据合适的换行符来读取一行数据,赋值给line
            while ((line = buffReader.readLine()) != null) {
                if (StringUtils.isNotBlank(line)) {
                    //数据不为空则加入列表
                    dataList.add(line);
                }
            }
        } catch (Exception e) {
            System.out.println("读取csv文件发生异常");
            e.printStackTrace();
        } finally {
            try {
                //关闭流
                if (buffReader != null) {
                    buffReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return dataList;
    }

    /**
     * 根据MultipartFile文件读取csv文件的内容
     * @return
     */
    public static List<String> readMultipartFile(MultipartFile file) {
        List<String> targetOrders = new ArrayList<>();
        try (
                Reader reader1 = new BufferedReader(new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8));
        ) {
            BufferedReader bReader1 = new BufferedReader(reader1);

            while (true) {
                String line1 = bReader1.readLine();
                if (line1 == null) {
                    break;
                }
                targetOrders.add(line1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return targetOrders;
    }

    /**
     * postman 发送并下载csv文件到桌面
     * @param filename
     * @param headers
     * @param dataList
     * @param request
     * @param response
     * @throws IOException
     */
    public static void exportByList(String filename, String[] headers, List<List<String>> dataList, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String agent = request.getHeader("User-Agent").toUpperCase(); // 浏览器信息
        if (agent.indexOf("MSIE") > 0 || (agent.indexOf("GECKO") > 0 && agent.indexOf("RV:11") > 0)) {  //IE浏览器和Edge浏览器
            filename = URLEncoder.encode(filename, "UTF-8");
        } else {  //其他浏览器
            filename = new String(filename.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
        }
        response.addHeader("Content-Disposition", "attachment;filename=" + filename);
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/octet-stream");
        OutputStream os = response.getOutputStream();// 取得输出流
        OutputStreamWriter osw;
        CSVFormat csvFormat;
        CSVPrinter csvPrinter = null;
        try {
            osw = new OutputStreamWriter(os, "GBK");//如果是UTF-8时，WPS打开是正常显示，而微软的excel打开是乱码,
            csvFormat = CSVFormat.DEFAULT.withHeader(headers);
            csvPrinter = new CSVPrinter(osw, csvFormat);
            for (List<String> values : dataList) {
                csvPrinter.printRecord(values);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(os, csvPrinter);
        }
    }

    private static void close(OutputStream os, CSVPrinter csvPrinter) {
        if (csvPrinter != null) {
            try {
                csvPrinter.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                csvPrinter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (os != null) {
            try {
                os.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static File asFile(String filePath, InputStream is) throws IOException{
        File tmp = new File(filePath);
        OutputStream os = new FileOutputStream(tmp);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        while ((bytesRead = is.read(buffer, 0, 8192)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
        is.close();
        os.close();
        return tmp;
    }
}
